<template>
  <view class="tree-container">
    <view
      v-for="(node, index) in flatTreeData"
      :key="node.label + index"
      :style="{ marginLeft: node.level * 20 + 'px' }"
      class="tree-node"
    >
      <!-- 当前节点 -->
      <view class="node-content">
        <!-- 展开/收起图标 -->
        <image
          v-if="node.children && node.children.length > 0"
          :src="node.expanded ? $getImageUrl('arr_down.png') : $getImageUrl('arr_up.png')"
          mode="aspectFit"
          class="w-34rpx h-34rpx"
          @click.stop="toggleExpand(node)"
        />
        <!-- 节点名称 -->
        <text class="node-label text-#1684FC" @click="toggleExpand(node)">{{ node.label }}</text>
        <!-- 自定义选择框 
        <image :src="node.checked ? checkedIcon : uncheckedIcon" class="checkbox-icon" @click="toggleCheck(node)" />
        -->
      </view>
    </view>
  </view>
</template>
 
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
 
// 定义树节点接口
interface TreeNode {
  label: string
  checked?: boolean
  expanded?: boolean
  children?: TreeNode[]
  level?: number // 添加层级信息
}
 
// 定义 props
const props = defineProps<{
  treeList: TreeNode[]
}>()
 
// 图标路径
/*
const checkedIcon = '/static/checkbox_checked.png' // 选中状态图标
const uncheckedIcon = '/static/checkbox_unchecked.png' // 未选中状态图标
const expandedIcon = '/static/arr_up.png' // 展开状态图标
const collapsedIcon = '/static/arr_down.png' // 收起状态图标
*/
 
// 记录所有勾选的节点
const checkedNodes = ref<TreeNode[]>([])
 
// 扁平化树形数据
const flatTreeData = computed(() => {
  const flatten = (nodes: TreeNode[], level = 0): TreeNode[] => {
    let result: TreeNode[] = []
    nodes.forEach((node) => {
      // 添加层级信息
      node.level = level
      result.push(node)
      // 如果节点展开且有子节点，递归处理子节点
      if (node.expanded && node.children) {
        result = result.concat(flatten(node.children, level + 1))
      }
    })
    return result
  }
  const v = flatten(props.treeList)
  return v
})
 
// 切换节点选中状态
const toggleCheck = (node: TreeNode) => {
  // 切换当前节点的选中状态
  node.checked = !node.checked
  // 如果当前节点是父节点，则勾选所有子节点
  if (node.children && node.children.length > 0) {
    toggleChildren(node, node.checked)
  }
  // 更新 checkedNodes
  updateCheckedNodes(node)
}
 
// 递归切换子节点状态
const toggleChildren = (node: TreeNode, checked: boolean) => {
  if (node.children) {
    node.children.forEach((child) => {
      child.checked = checked
      toggleChildren(child, checked) // 递归处理子节点
    })
  }
}
 
// 更新 checkedNodes
const updateCheckedNodes = (node: TreeNode) => {
  if (node.checked) {
    checkedNodes.value.push(node)
  } else {
    checkedNodes.value = checkedNodes.value.filter((n) => n !== node)
  }
  console.log('当前勾选的节点:', checkedNodes.value)
}
 
// 切换节点展开状态
const toggleExpand = (node: TreeNode) => {
  if (node.children && node.children.length > 0) {
    node.expanded = !node.expanded
  }
}
 
// 递归为所有节点添加 checked 和 expanded 属性
const initTreeData = (nodes: TreeNode[]) => {
  nodes.forEach((node) => {
    node.checked = false // 默认不选中
    node.expanded = false // 默认不展开
    if (node.children) {
      initTreeData(node.children) // 递归处理子节点
    }
  })
}
 
// 监听 treeList 的变化，初始化数据
watch(
  () => props.treeList,
  (newVal) => {
    if (newVal && newVal.length > 0) {
      initTreeData(newVal) // 初始化 checked 和 expanded 属性
    }
  },
  { immediate: true }
)
</script>
 
<style scoped>
.tree-container {
  padding: 20px;
}
 
.tree-node {
  margin-bottom: 8px;
}
 
.node-content {
  display: flex;
  align-items: center;
}
 
.checkbox-icon {
  width: 20px;
  height: 20px;
  margin-right: 8px;
}
 
.node-label {
  flex: 1;
}
 
.expand-icon {
  width: 16px;
  height: 16px;
  margin-left: 8px;
}
</style>